package com.example.opengldemo.simple_13_02;

import java.util.ArrayList;

import android.opengl.GLES30;

import com.example.opengldemo.util.MatrixState;
import com.example.opengldemo.util.ShaderBuffer;
import com.example.opengldemo.util.ShaderHandle;
import com.example.opengldemo.util.ShaderUtil;

public class Ball {


    String mVertexShader;
    String mFragmentShader;

    float xAngle = 0;
    float yAngle = 0;
    float zAngle = 0;

    float bHalf = 0;
    float r = 0;

    public Ball(MySurfaceView mv, float scale, float aHalf, int n) {
        initVertexData(scale, aHalf, n);
        initShader(mv);
    }

    public void initVertexData(float scale, float aHalf, int n) {
        aHalf *= scale;
        shaderBuffer = new ShaderBuffer() ;
        bHalf = aHalf * 0.618034f;
        r = (float) Math.sqrt(aHalf * aHalf + bHalf * bHalf);
        ArrayList<Float> alVertix20 = new ArrayList<Float>();
        ArrayList<Integer> alFaceIndex20 = new ArrayList<Integer>();
        alVertix20.add(0f);
        alVertix20.add(aHalf);
        alVertix20.add(-bHalf);

        alVertix20.add(0f);
        alVertix20.add(aHalf);
        alVertix20.add(bHalf);
        alVertix20.add(aHalf);
        alVertix20.add(bHalf);
        alVertix20.add(0f);
        alVertix20.add(bHalf);
        alVertix20.add(0f);
        alVertix20.add(-aHalf);
        alVertix20.add(-bHalf);
        alVertix20.add(0f);
        alVertix20.add(-aHalf);
        alVertix20.add(-aHalf);
        alVertix20.add(bHalf);
        alVertix20.add(0f);

        alVertix20.add(-bHalf);
        alVertix20.add(0f);
        alVertix20.add(aHalf);
        alVertix20.add(bHalf);
        alVertix20.add(0f);
        alVertix20.add(aHalf);
        alVertix20.add(aHalf);
        alVertix20.add(-bHalf);
        alVertix20.add(0f);
        alVertix20.add(0f);
        alVertix20.add(-aHalf);
        alVertix20.add(-bHalf);
        alVertix20.add(-aHalf);
        alVertix20.add(-bHalf);
        alVertix20.add(0f);

        alVertix20.add(0f);
        alVertix20.add(-aHalf);
        alVertix20.add(bHalf);
        alFaceIndex20.add(0);
        alFaceIndex20.add(1);
        alFaceIndex20.add(2);
        alFaceIndex20.add(0);
        alFaceIndex20.add(2);
        alFaceIndex20.add(3);
        alFaceIndex20.add(0);
        alFaceIndex20.add(3);
        alFaceIndex20.add(4);
        alFaceIndex20.add(0);
        alFaceIndex20.add(4);
        alFaceIndex20.add(5);
        alFaceIndex20.add(0);
        alFaceIndex20.add(5);
        alFaceIndex20.add(1);

        alFaceIndex20.add(1);
        alFaceIndex20.add(6);
        alFaceIndex20.add(7);
        alFaceIndex20.add(1);
        alFaceIndex20.add(7);
        alFaceIndex20.add(2);
        alFaceIndex20.add(2);
        alFaceIndex20.add(7);
        alFaceIndex20.add(8);
        alFaceIndex20.add(2);
        alFaceIndex20.add(8);
        alFaceIndex20.add(3);
        alFaceIndex20.add(3);
        alFaceIndex20.add(8);
        alFaceIndex20.add(9);
        alFaceIndex20.add(3);
        alFaceIndex20.add(9);
        alFaceIndex20.add(4);
        alFaceIndex20.add(4);
        alFaceIndex20.add(9);
        alFaceIndex20.add(10);
        alFaceIndex20.add(4);
        alFaceIndex20.add(10);
        alFaceIndex20.add(5);
        alFaceIndex20.add(5);
        alFaceIndex20.add(10);
        alFaceIndex20.add(6);
        alFaceIndex20.add(5);
        alFaceIndex20.add(6);
        alFaceIndex20.add(1);

        alFaceIndex20.add(6);
        alFaceIndex20.add(11);
        alFaceIndex20.add(7);
        alFaceIndex20.add(7);
        alFaceIndex20.add(11);
        alFaceIndex20.add(8);
        alFaceIndex20.add(8);
        alFaceIndex20.add(11);
        alFaceIndex20.add(9);
        alFaceIndex20.add(9);
        alFaceIndex20.add(11);
        alFaceIndex20.add(10);
        alFaceIndex20.add(10);
        alFaceIndex20.add(11);
        alFaceIndex20.add(6);
        float[] vertices20 = VectorUtil.calVertices(alVertix20, alFaceIndex20);

        ArrayList<Float> alVertix = new ArrayList<Float>();
        ArrayList<Integer> alFaceIndex = new ArrayList<Integer>();
        int vnCount = 0;
        for (int k = 0; k < vertices20.length; k += 9) {
            float[] v1 = new float[]{vertices20[k + 0], vertices20[k + 1], vertices20[k + 2]};
            float[] v2 = new float[]{vertices20[k + 3], vertices20[k + 4], vertices20[k + 5]};
            float[] v3 = new float[]{vertices20[k + 6], vertices20[k + 7], vertices20[k + 8]};

            for (int i = 0; i <= n; i++) {
                float[] viStart = VectorUtil.devideBall(r, v1, v2, n, i);
                float[] viEnd = VectorUtil.devideBall(r, v1, v3, n, i);
                for (int j = 0; j <= i; j++) {
                    float[] vi = VectorUtil.devideBall(r, viStart, viEnd, i, j);
                    alVertix.add(vi[0]);
                    alVertix.add(vi[1]);
                    alVertix.add(vi[2]);
                }
            }

            for (int i = 0; i < n; i++) {
                if (i == 0) {
                    alFaceIndex.add(vnCount + 0);
                    alFaceIndex.add(vnCount + 1);
                    alFaceIndex.add(vnCount + 2);
                    vnCount += 1;
                    if (i == n - 1) {
                        vnCount += 2;
                    }
                    continue;
                }
                int iStart = vnCount;
                int viCount = i + 1;
                int iEnd = iStart + viCount - 1;

                int iStartNext = iStart + viCount;
                int viCountNext = viCount + 1;
                int iEndNext = iStartNext + viCountNext - 1;

                for (int j = 0; j < viCount - 1; j++) {
                    int index0 = iStart + j;
                    int index1 = index0 + 1;
                    int index2 = iStartNext + j;
                    int index3 = index2 + 1;
                    alFaceIndex.add(index0);
                    alFaceIndex.add(index2);
                    alFaceIndex.add(index3);
                    alFaceIndex.add(index0);
                    alFaceIndex.add(index3);
                    alFaceIndex.add(index1);
                }// j
                alFaceIndex.add(iEnd);
                alFaceIndex.add(iEndNext - 1);
                alFaceIndex.add(iEndNext);
                vnCount += viCount;
                if (i == n - 1) {
                    vnCount += viCountNext;
                }
            }
        }
        float[] vertices = VectorUtil.calVertices(alVertix, alFaceIndex);
        float[] normals = vertices;
        shaderBuffer.setVertexBuffer(vertices);
        shaderBuffer.setNormalBuffer(normals);
        float[] colors = new float[shaderBuffer.vCount * 4];
        int Count = 0;
        for (int i = 0; i < shaderBuffer.vCount; i++) {
            colors[Count++] = 1;    //r
            colors[Count++] = 1;    //g
            colors[Count++] = 1;    //b
            colors[Count++] = 1;    //a

        }
        shaderBuffer.setColorBuffer(colors);
    }
    ShaderHandle shaderHandle ;
    ShaderBuffer shaderBuffer ;
    public void initShader(MySurfaceView mv) {
        mVertexShader = ShaderUtil.loadFromAssetsFile("simple_13_02/vertex_color_light.sh", mv.getResources());
        mFragmentShader = ShaderUtil.loadFromAssetsFile("simple_13_02/frag_color_light.sh", mv.getResources());
        shaderHandle = new ShaderHandle(ShaderUtil.createProgram(mVertexShader, mFragmentShader) );
    }

    public void drawSelf() {
        MatrixState.rotate(xAngle, 1, 0, 0);
        MatrixState.rotate(yAngle, 0, 1, 0);
        MatrixState.rotate(zAngle, 0, 0, 1);
        shaderHandle.program()
                .bindMMaxtrixHandle()
                .bindMVPMaxtrixHandle()
                .bindCameraHandle()
                .bindLightHandle()
                .bindVertexHandle(shaderBuffer.getVertexBuffer())
                .bindNormalHandle(shaderBuffer.getNormalBuffer())
                .bindColorsHandle(shaderBuffer.getColorBuffer()) ;
        GLES30.glLineWidth(2);
        shaderHandle.run(GLES30.GL_LINE_STRIP ,shaderBuffer.vCount);
    }
}
